package heima_design.model05;
/**
 * @ClassName: Singleton
 * @Description: 懒汉式-方式3（双重检查锁）
 * @Version: v1.0.0
 * @Author: tamir
 * @Date: 2022/06/02
 * Modification History:
 * Date             Author      Version     Description
 * -------------------------------------------------------------
 * 2022/06/02      tamir        v1.0.0      创建
 */
public class Singleton {
	private Singleton(){}
	
	private static Singleton instance;
	
	public static Singleton getInstance(){
		//第一次判断，如果instance不为null,不进入强锁阶段，直接返回实例
		if (instance == null){
			synchronized (Singleton.class){
				//抢到锁之后再次判断是否为null
				if (instance == null){
					instance = new Singleton(); //error
				}
			}
		}
		return instance;
	}
	//隐患
	//上述写法看似解决了问题，但是有个很大的隐患。实例化对象的那行代码（标记为error的那行），实际上可以分解成以下三个步骤：
	//
	//分配内存空间
	//初始化对象
	//将对象指向刚分配的内存空间
	//但是有些编译器为了性能的原因，可能会将第二步和第三步进行重排序，顺序就成了：
	//
	//分配内存空间
	//将对象指向刚分配的内存空间
	//初始化对象
	//现在考虑重排序后，两个线程发生了以下调用：
	//
	//Time	    Thread A	                       Thread B
	//T1	    检查到instance为空
	//T2	    获取锁
	//T3	    再次检查到instance为空
	//T4	    为instance分配内存空间
	//T5	    将instance指向内存空间
	//T6	    	                               检查到instance不为空
	//T7	    	                               访问instance（此时对象还未完成初始化）
	//T8	    初始化instance
	//在这种情况下，T7时刻线程B对instance的访问，访问的是一个初始化未完成的对象。
}
